package com.learning.spring.ioc.container;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * ClassName: ApplicationContextIoc
 * Description: ApplicationContext 应用上下文, 建立在 BeanFactory 基础之上，扩展了国际化支持（MessageSource）、框架事件（ApplicationEventPublisher）
 * ApplicationContext 是面向使用Spring 框架的开发者
 * Date: 2018/7/26 14:51 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class ContainerApplicationContext {


    public static void main(String[] args) {
//        test2();
        test3();
    }

    /**
     * ApplicationContext 类体系结构：主要是 ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、AnnotationConfigApplicationContext
     * 1. 继承了 ListableBeanFactory、HierarchicalBeanFactory接口，又扩展了 BeanFactory 功能
     * 2. ApplicationEventPublisher：让容器拥有发布上下文事件的功能。AbstractApplicationContext
     * 3. MessageSource：为应用提供 i18n 国际化
     * 4. ResourcePatternResolver：让所有的ApplicationContext实现了类似 PathMatchingResourcePatternResolver 的功能。通过带前缀的Ant风格的资源文件路径装载spring
     * 5. Lifecycle：（ConfigurableApplicationContext 继承），提供start()、stop() 两个方法，主要用于控制异步处理过程。
     * <p>
     * ConfigurableApplicationContext 扩展了 ApplicationContext ，新增两个主要方法 refresh()、close()。让ApplicationContext具有启动、刷新、关闭应用上下文的能力
     *
     * @param
     */
    static void test() {

    }

    /**
     * ApplicationContext 初始化：初始化的容器会实例化bean
     */
    static void test2() {
        // 一般xml配置，在classpath下优先使用 ClassPathXmlApplicationContext
        // spring-context.xml 等同于 classpath:spring-context.xml
        // 初始化的容器会实例化bean，所以一开始启动会比BeanFactory 慢一点
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");

        System.out.println("初始化 ApplicationContext 完成，同时实例化 bean");

        BeanContainer beanContainer = context.getBean("beanContainer", BeanContainer.class);
        beanContainer.done();
        ((ClassPathXmlApplicationContext) context).close();
        /*
        BeanContainerImpl 被实例化了
        初始化 ApplicationContext 完成，同时实例化 bean
        BeanContainerImpl.do() 方法被调用~~
        */
    }

    /**
     * Java Config 实现（Java-based）
     * 使用 @Configuration @Bean 注解，这个单独用一个工程来学习
     */
    static void test3() {
        /*AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(AnnotationConfig.class);
        // 第一次 refresh 是启动，再次就是刷新
        context.refresh();*/

        // AnnotationConfig 配置类，相当于<beans> 标签
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationConfig.class);
        System.out.println("初始化 AnnotationConfigApplicationContext 完成， 同时实例化 bean");

        BeanContainer beanContainer = context.getBean("annotationBean", BeanContainer.class);
        beanContainer.done();
        context.close();

        /*
        BeanContainerImpl 被实例化了
        初始化 AnnotationConfigApplicationContext 完成
        BeanContainerImpl.do() 方法被调用~~
        */
    }

}


